import os
import time
from typing import Union, List

from scripts.device.Device import Device


class FastbootDevice(Device):
    FASTBOOT_BIN = os.path.join('bin', 'fastboot.exe')
    _BIN: Union[None, str] = None

    def __init__(self, sn: str):
        self._sn = sn

    @staticmethod
    def bin() -> str:
        if FastbootDevice._BIN is None:
            FastbootDevice._BIN = os.path.join(Device.script_dir(), FastbootDevice.FASTBOOT_BIN)
        return FastbootDevice._BIN

    def sn(self):
        return self._sn

    @staticmethod
    def static_exec(cmd: str) -> List[str]:
        return Device.exec_raw('%s %s 2>&1' % (FastbootDevice.bin(), cmd))

    def exec(self, cmd: str) -> List[str]:
        return FastbootDevice.static_exec('-s %s %s' % (self.sn(), cmd))

    @staticmethod
    def devices() -> List[str]:
        lines = FastbootDevice.static_exec('devices 2>&1')
        return [line.split()[0] for line in lines]

    @staticmethod
    def wait_for_device(sn: Union[None, str] = None):
        while True:
            devices = FastbootDevice.devices()
            if len(devices) > 0:
                if sn is None:
                    return FastbootDevice(devices[0])
                elif sn in devices:
                    return FastbootDevice(sn)
            time.sleep(1)

    def enable_root_9(self) -> bool:
        lines = self.exec('oem enable-rooting')
        return len(lines) > 0 and lines[0].startswith('OKAY')

    def disable_root_9(self) -> bool:
        lines = self.exec('oem disable-rooting')
        return len(lines) > 0 and lines[0].startswith('OKAY')

    def enable_root_11(self) -> bool:
        lines = self.exec('oem enable-root')
        return len(lines) > 0 and lines[0].startswith('OKAY')

    def disable_root_11(self) -> bool:
        lines = self.exec('oem disable-root')
        return len(lines) > 0 and lines[0].startswith('OKAY')

    def reboot(self):
        self.exec('reboot')

    def unlock(self):
        self.exec('flashing unlock')

    def lock(self):
        self.exec('flashing lock')

    def get_var(self, name: str, def_val: Union[None, str] = None) -> Union[None, str]:
        lines = self.exec('getvar %s 2>&1 | findstr %s'
                          % (name, name))
        if len(lines) <= 0:
            return def_val

        line = lines[0]
        return line[len(name)+1:].strip()
